Skip to content

Don’t report missing fields in struct exprs with syntax errors.#153227

Merged
rust-bors[bot] merged 3 commits intorust-lang:mainfrom
kpreid:struct-missing-field
Mar 3, 2026
Merged

Don’t report missing fields in struct exprs with syntax errors.#153227
rust-bors[bot] merged 3 commits intorust-lang:mainfrom
kpreid:struct-missing-field

Conversation

@kpreid
Copy link
Contributor

@kpreid kpreid commented Feb 28, 2026

View all comments

@Noratrieb told me that “it is a bug if this recovery causes follow-up errors that would not be there if the user fixed the first error.” So, here’s a contribution to hide a follow-up error that annoyed me recently.

Specifically, if the user writes a struct literal with a syntax error, such as

StructName { foo: 1 bar: 2 }

the compiler will no longer report that the field bar is missing in addition to the syntax error.

This is my first time attempting any change to the parser or AST; please let me know if there is a better way to do what I’ve done here. The part I’m least happy with is the blast radius of adding another field to hir::ExprKind::Struct, but this seems to be in line with the style of the rest of the code. (If this were my own code, I would consider changing hir::ExprKind::Struct to a nested struct, the same way it is in ast::ExprKind.) The additional information is now stored as an additional variant of ast::StructRest / hir::StructTailExpr.

Note to reviewers: I recommend reviewing each commit separately, and in the case of the first one with indentation changes ignored.

@rustbot
Copy link
Collaborator

rustbot commented Feb 28, 2026

Some changes occurred in need_type_info.rs

cc @lcnr

Some changes occurred in src/tools/rustfmt

cc @rust-lang/rustfmt

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustfmt Relevant to the rustfmt team, which will review and decide on the PR/issue. labels Feb 28, 2026
@rustbot
Copy link
Collaborator

rustbot commented Feb 28, 2026

r? @JohnTitor

rustbot has assigned @JohnTitor.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 69 candidates
  • Random selection from 15 candidates

@kpreid
Copy link
Contributor Author

kpreid commented Feb 28, 2026

The only changes to rustfmt and clippy are necessary added _ patterns.

@rustbot label -T-clippy -T-rustfmt

@rustbot rustbot removed T-clippy Relevant to the Clippy team. T-rustfmt Relevant to the rustfmt team, which will review and decide on the PR/issue. labels Feb 28, 2026
@Noratrieb
Copy link
Member

Noratrieb commented Feb 28, 2026

Thanks, these types of fixes are exactly what I was talking about!
An alternative that's less "infectious" would be to recover the invalid struct expr into an error expr, but that'd lose out on the correct fields, so I think this approach is good too.
I won't have time to review it in detail though, so I'll leave that to others.

@fmease
Copy link
Member

fmease commented Feb 28, 2026

Size increase of not uncommonly used AST & HIR nodes. @bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot pushed a commit that referenced this pull request Feb 28, 2026
Don’t report missing fields in struct exprs with syntax errors.
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Feb 28, 2026
Copy link
Member

@fmease fmease Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively to all of this we could 'just' make the parser recovery smarter and try to recover $path { $ident: $expr $ident: $expr } (and similar) as $path { $ident: $expr, $ident: $expr } instead of $path { $ident: /*error*/ } which is what we currently seem to do.

Copy link
Contributor Author

@kpreid kpreid Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That helps with the comma being missing, but not with other parse errors. For example, suppose the field name is missing:

struct SomeStruct {
    foo: u16,
    bar: bool,
}

fn make_foo() -> u16 { 0xF00 }

fn example() -> SomeStruct {
    SomeStruct {
        /* foo: */ make_foo(),
        bar: true,
    }
}

The parser can’t reasonably recover into knowing that a foo field should be present. It could recover into something like ..<ExprKind::Err> to make the expression valid without foo, but that could provoke further errors itself (e.g. private/non-exhaustive fields).

Regarding the concern over the AST being larger, what if ast::StructRest/hir::StructTailExpr was given a fourth variant to mark the parse error recovery? That would take up no additional memory, and I think it would work out fairly cleanly, since the missing field error it is meant to suppress can only happen if the struct does not have any .., and it acts a little bit like recovering into there being an ... In fact, now that I’ve written it out, I like this idea better than having an independent error-flag field. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the perf-regression, I’ve gone ahead and pushed a revised version with the above implementation strategy.

Note: I recommend reviewing commit by commit, and with indentation changes ignored.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That helps with the comma being missing, but not with other parse errors. For example, suppose the field name is missing

Fair 👍

@rust-bors
Copy link
Contributor

rust-bors bot commented Feb 28, 2026

☀️ Try build successful (CI)
Build commit: 4e1e63f (4e1e63fbcf35b1a967f73690bb089425440a612e, parent: ba1567989ee7774a1fb53aa680a8e4e8daa0f519)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (4e1e63f): comparison URL.

Overall result: ❌ regressions - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
0.3% [0.1%, 0.4%] 10
Regressions ❌
(secondary)
0.4% [0.2%, 0.6%] 36
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.0% [-0.0%, -0.0%] 1
All ❌✅ (primary) 0.3% [0.1%, 0.4%] 10

Max RSS (memory usage)

This benchmark run did not return any relevant results for this metric.

Cycles

Results (primary 2.6%, secondary -4.2%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.6% [2.6%, 2.6%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-4.2% [-4.2%, -4.2%] 1
All ❌✅ (primary) 2.6% [2.6%, 2.6%] 1

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 479.975s -> 483.021s (0.63%)
Artifact size: 395.63 MiB -> 397.68 MiB (0.52%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Mar 1, 2026
This refactor will make an upcoming change smaller, and also adds
exhaustive matching.
This adds a variant `NoneWithError` to AST and HIR representations of
the “rest” or “tail”, which is currently always treated identically to
the `None` variant.
@kpreid kpreid force-pushed the struct-missing-field branch from c6432b7 to 83cdfcb Compare March 1, 2026 02:20
@rustbot rustbot added T-clippy Relevant to the Clippy team. T-rustfmt Relevant to the rustfmt team, which will review and decide on the PR/issue. labels Mar 1, 2026
@kpreid kpreid force-pushed the struct-missing-field branch from 83cdfcb to 02f6b3a Compare March 1, 2026 02:26
@JohnTitor
Copy link
Member

r? fmease

@rustbot rustbot removed the perf-regression Performance regression. label Mar 2, 2026
@fmease
Copy link
Member

fmease commented Mar 2, 2026

r? estebank

@rustbot rustbot assigned estebank and unassigned fmease Mar 2, 2026
@fmease
Copy link
Member

fmease commented Mar 2, 2026

I believe that this is the right approach. r=me

#153227 (comment)

@bors r=estebank rollup-

@rust-bors
Copy link
Contributor

rust-bors bot commented Mar 2, 2026

📌 Commit f5d3b15 has been approved by estebank

It is now in the queue for this repository.

@rust-bors rust-bors bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 2, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Mar 2, 2026
…ebank

Don’t report missing fields in struct exprs with syntax errors.

@Noratrieb [told me](https://internals.rust-lang.org/t/custom-cargo-command-to-show-only-errors-avoid-setting-rustflags-every-time/24032/7?u=kpreid) that “it is a bug if this recovery causes follow-up errors that would not be there if the user fixed the first error.” So, here’s a contribution to hide a follow-up error that annoyed me recently.

Specifically, if the user writes a struct literal with a syntax error, such as

```rust
StructName { foo: 1 bar: 2 }
```

the compiler will no longer report that the field `bar` is missing in addition to the syntax error.

This is my first time attempting any change to the parser or AST; please let me know if there is a better way to do what I’ve done here. ~~The part I’m least happy with is the blast radius of adding another field to `hir::ExprKind::Struct`, but this seems to be in line with the style of the rest of the code. (If this were my own code, I would consider changing `hir::ExprKind::Struct` to a nested struct, the same way it is in `ast::ExprKind`.)~~ The additional information is now stored as an additional variant of `ast::StructRest` / `hir::StructTailExpr`.

**Note to reviewers:** I recommend reviewing each commit separately, and in the case of the first one with indentation changes ignored.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Mar 2, 2026
…ebank

Don’t report missing fields in struct exprs with syntax errors.

@Noratrieb [told me](https://internals.rust-lang.org/t/custom-cargo-command-to-show-only-errors-avoid-setting-rustflags-every-time/24032/7?u=kpreid) that “it is a bug if this recovery causes follow-up errors that would not be there if the user fixed the first error.” So, here’s a contribution to hide a follow-up error that annoyed me recently.

Specifically, if the user writes a struct literal with a syntax error, such as

```rust
StructName { foo: 1 bar: 2 }
```

the compiler will no longer report that the field `bar` is missing in addition to the syntax error.

This is my first time attempting any change to the parser or AST; please let me know if there is a better way to do what I’ve done here. ~~The part I’m least happy with is the blast radius of adding another field to `hir::ExprKind::Struct`, but this seems to be in line with the style of the rest of the code. (If this were my own code, I would consider changing `hir::ExprKind::Struct` to a nested struct, the same way it is in `ast::ExprKind`.)~~ The additional information is now stored as an additional variant of `ast::StructRest` / `hir::StructTailExpr`.

**Note to reviewers:** I recommend reviewing each commit separately, and in the case of the first one with indentation changes ignored.
rust-bors bot pushed a commit that referenced this pull request Mar 3, 2026
…uwer

Rollup of 8 pull requests

Successful merges:

 - #151864 (Implement AST -> HIR generics propagation in delegation)
 - #152941 (prefer actual ABI-controling fields over target.abi when making ABI decisions)
 - #153227 (Don’t report missing fields in struct exprs with syntax errors.)
 - #152966 (Migrate 11 tests from tests/ui/issues to specific directories)
 - #153003 (rustdoc: make `--emit` and `--out-dir` mimic rustc)
 - #153034 (Remove unhelpful hint from trivial bound errors)
 - #153221 (Add release notes for 1.94.0)
 - #153297 (Update the name of the Hermit operating system)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Mar 3, 2026
…ebank

Don’t report missing fields in struct exprs with syntax errors.

@Noratrieb [told me](https://internals.rust-lang.org/t/custom-cargo-command-to-show-only-errors-avoid-setting-rustflags-every-time/24032/7?u=kpreid) that “it is a bug if this recovery causes follow-up errors that would not be there if the user fixed the first error.” So, here’s a contribution to hide a follow-up error that annoyed me recently.

Specifically, if the user writes a struct literal with a syntax error, such as

```rust
StructName { foo: 1 bar: 2 }
```

the compiler will no longer report that the field `bar` is missing in addition to the syntax error.

This is my first time attempting any change to the parser or AST; please let me know if there is a better way to do what I’ve done here. ~~The part I’m least happy with is the blast radius of adding another field to `hir::ExprKind::Struct`, but this seems to be in line with the style of the rest of the code. (If this were my own code, I would consider changing `hir::ExprKind::Struct` to a nested struct, the same way it is in `ast::ExprKind`.)~~ The additional information is now stored as an additional variant of `ast::StructRest` / `hir::StructTailExpr`.

**Note to reviewers:** I recommend reviewing each commit separately, and in the case of the first one with indentation changes ignored.
rust-bors bot pushed a commit that referenced this pull request Mar 3, 2026
…uwer

Rollup of 12 pull requests

Successful merges:

 - #152941 (prefer actual ABI-controling fields over target.abi when making ABI decisions)
 - #153227 (Don’t report missing fields in struct exprs with syntax errors.)
 - #153265 (Clarified doc comments + added tests confirming current behavior for intersperse/intersperse_with)
 - #152966 (Migrate 11 tests from tests/ui/issues to specific directories)
 - #153003 (rustdoc: make `--emit` and `--out-dir` mimic rustc)
 - #153034 (Remove unhelpful hint from trivial bound errors)
 - #153152 (Migration of LintDiagnostic - part 5)
 - #153177 (disable the ptr_fragment_in_final test on s390x)
 - #153221 (Add release notes for 1.94.0)
 - #153279 (feat: Provide an '.item_kind()' method on ItemEnum)
 - #153297 (Update the name of the Hermit operating system)
 - #153309 (Cleanup of c-variadic link test)
@rust-bors rust-bors bot merged commit 7174c10 into rust-lang:main Mar 3, 2026
12 checks passed
@rustbot rustbot added this to the 1.96.0 milestone Mar 3, 2026
rust-timer added a commit that referenced this pull request Mar 3, 2026
Rollup merge of #153227 - kpreid:struct-missing-field, r=estebank

Don’t report missing fields in struct exprs with syntax errors.

@Noratrieb [told me](https://internals.rust-lang.org/t/custom-cargo-command-to-show-only-errors-avoid-setting-rustflags-every-time/24032/7?u=kpreid) that “it is a bug if this recovery causes follow-up errors that would not be there if the user fixed the first error.” So, here’s a contribution to hide a follow-up error that annoyed me recently.

Specifically, if the user writes a struct literal with a syntax error, such as

```rust
StructName { foo: 1 bar: 2 }
```

the compiler will no longer report that the field `bar` is missing in addition to the syntax error.

This is my first time attempting any change to the parser or AST; please let me know if there is a better way to do what I’ve done here. ~~The part I’m least happy with is the blast radius of adding another field to `hir::ExprKind::Struct`, but this seems to be in line with the style of the rest of the code. (If this were my own code, I would consider changing `hir::ExprKind::Struct` to a nested struct, the same way it is in `ast::ExprKind`.)~~ The additional information is now stored as an additional variant of `ast::StructRest` / `hir::StructTailExpr`.

**Note to reviewers:** I recommend reviewing each commit separately, and in the case of the first one with indentation changes ignored.
@kpreid kpreid deleted the struct-missing-field branch March 4, 2026 00:16
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Mar 5, 2026
…t-syntax-error, r=dingxiangfei2009

fix(thir): Include `NoneWithError` in Enum Struct Tail Assertion

### Summary:

Fixes the ICE triggered when a syntax error appears inside an enum variant struct literal.

PR rust-lang#153227 added `StructTailExpr::NoneWithError` and updated the `match base` arm in the `AdtKind::Enum` branch of `thir/cx/expr.rs`, but overlooked the `assert!(matches!(...))` guard preceding it, which still only listed `None | DefaultFields(_)`.

Closes rust-lang#153390

r? @dingxiangfei2009
cc @matthiaskrgr
rust-timer added a commit that referenced this pull request Mar 5, 2026
Rollup merge of #153394 - TKanX:bugfix/153390-ice-enum-struct-syntax-error, r=dingxiangfei2009

fix(thir): Include `NoneWithError` in Enum Struct Tail Assertion

### Summary:

Fixes the ICE triggered when a syntax error appears inside an enum variant struct literal.

PR #153227 added `StructTailExpr::NoneWithError` and updated the `match base` arm in the `AdtKind::Enum` branch of `thir/cx/expr.rs`, but overlooked the `assert!(matches!(...))` guard preceding it, which still only listed `None | DefaultFields(_)`.

Closes #153390

r? @dingxiangfei2009
cc @matthiaskrgr
flip1995 pushed a commit to flip1995/rust that referenced this pull request Mar 5, 2026
…ebank

Don’t report missing fields in struct exprs with syntax errors.

@Noratrieb [told me](https://internals.rust-lang.org/t/custom-cargo-command-to-show-only-errors-avoid-setting-rustflags-every-time/24032/7?u=kpreid) that “it is a bug if this recovery causes follow-up errors that would not be there if the user fixed the first error.” So, here’s a contribution to hide a follow-up error that annoyed me recently.

Specifically, if the user writes a struct literal with a syntax error, such as

```rust
StructName { foo: 1 bar: 2 }
```

the compiler will no longer report that the field `bar` is missing in addition to the syntax error.

This is my first time attempting any change to the parser or AST; please let me know if there is a better way to do what I’ve done here. ~~The part I’m least happy with is the blast radius of adding another field to `hir::ExprKind::Struct`, but this seems to be in line with the style of the rest of the code. (If this were my own code, I would consider changing `hir::ExprKind::Struct` to a nested struct, the same way it is in `ast::ExprKind`.)~~ The additional information is now stored as an additional variant of `ast::StructRest` / `hir::StructTailExpr`.

**Note to reviewers:** I recommend reviewing each commit separately, and in the case of the first one with indentation changes ignored.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Mar 5, 2026
Fix ICEs due to incomplete typechecking on struct literals with syntax errors.

Fixes rust-lang#153388.
Followup to rust-lang#153227.

Today I have learned that when we don’t emit a diagnostic *specifically from typeck*, we need to call `self.infcx.set_tainted_by_errors()` to signal that the type checking is incomplete despite the lack of error.

r? fmease
rust-timer added a commit that referenced this pull request Mar 5, 2026
Rollup merge of #153453 - kpreid:fix-153388, r=fmease,estebank

Fix ICEs due to incomplete typechecking on struct literals with syntax errors.

Fixes #153388.
Followup to #153227.

Today I have learned that when we don’t emit a diagnostic *specifically from typeck*, we need to call `self.infcx.set_tainted_by_errors()` to signal that the type checking is incomplete despite the lack of error.

r? fmease
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustfmt Relevant to the rustfmt team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants